package com.wht.service;

import org.apache.http.Header;
import org.apache.http.HeaderIterator;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.HttpClientUtils;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.springframework.stereotype.Service;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Service
public class CrawlerService {

    private static final String USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; WOW64) " +
            "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36";

    private static final Pattern pattern = Pattern.compile("JSESSIONID=(.*); Path=/eams");

    private static final DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");

    private static Date lastLoginTime = null;

    private static String ljsd = null;

    private String login() {
        //上次登录在10分钟内直接使用上次的JSESSIONID
        if (ljsd != null && lastLoginTime != null) {
            if (lastLoginTime.getTime() + 10 * 60 * 1000 > new Date().getTime()) {
                return ljsd;
            }
        }

        //生成httpclient，相当于该打开一个浏览器
        CloseableHttpClient httpClient = HttpClients.createDefault();
        //设置请求和传输超时时间
        RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(2000).setConnectTimeout(2000).build();
        CloseableHttpResponse response = null;
        HttpPost request = new HttpPost("http://us.nwpu.edu.cn/eams/login.action");
        request.setConfig(requestConfig);
        try {
            List<NameValuePair> nvps = new ArrayList<NameValuePair>();
            nvps.add(new BasicNameValuePair("username", "宝，这可不兴看啊"));
            nvps.add(new BasicNameValuePair("password", "宝，这个更不能看啊"));
            nvps.add(new BasicNameValuePair("encodedPassword", ""));
            nvps.add(new BasicNameValuePair("session_locale", "zh_CN"));
            request.setEntity(new UrlEncodedFormEntity(nvps));

            //执行get请求，相当于在输入地址栏后敲回车键
            response = httpClient.execute(request);

            HeaderIterator iterator = response.headerIterator();

            while (iterator.hasNext()) {
                Header header = iterator.nextHeader();
                if (header.getName().equals("Set-Cookie")) {
                    String value = header.getValue();
                    Matcher matcher = pattern.matcher(value);
                    if (matcher.find()) {
                        String jid = matcher.group(1);
                        lastLoginTime = new Date();
                        ljsd = jid;
                        return jid;
                    }
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            HttpClientUtils.closeQuietly(response);
            HttpClientUtils.closeQuietly(httpClient);
        }
        return null;
    }

    private HttpPost getRequest(String jid) {

        HttpPost request = new HttpPost("http://us.nwpu.edu.cn/eams/classroom/apply/free!search.action");
        request.addHeader("Host", "us.nwpu.edu.cn");
        request.addHeader("Origin", "http://us.nwpu.edu.cn");
        request.addHeader("Cookie", "JSESSIONID=" + jid + ";");
        request.addHeader("Referer", "http://us.nwpu.edu.cn/eams/classroom/apply/free!search.action");
        request.addHeader("User-Agent", USER_AGENT);
        request.addHeader("X-Requested-With", "XMLHttpRequest");
        //设置请求和传输超时时间
        RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(2000).setConnectTimeout(2000).build();
        request.setConfig(requestConfig);
        return request;
    }

    private String getHtml(String jid, List<NameValuePair> nvps) {
        //生成httpclient，相当于该打开一个浏览器
        CloseableHttpClient httpClient = HttpClients.createDefault();
        //构建POST请求
        HttpPost request = getRequest(jid);

        CloseableHttpResponse response = null;
        try {
            request.setEntity(new UrlEncodedFormEntity(nvps));
            //执行get请求，相当于在输入地址栏后敲回车键
            response = httpClient.execute(request);

            if (response.getStatusLine().getStatusCode() == 200) {
                return EntityUtils.toString(response.getEntity(), "UTF-8");
            } else {
                System.out.println(Arrays.toString(response.getAllHeaders()));
                System.out.println("访问错误，状态码：" + response.getStatusLine().getStatusCode());
                return null;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            HttpClientUtils.closeQuietly(response);
            HttpClientUtils.closeQuietly(httpClient);
        }
    }

    private List<NameValuePair> getNameValuePair(String timeBegin, String timeEnd) {
        List<NameValuePair> nvps = new ArrayList<>();
        nvps.add(new BasicNameValuePair("classroom.type.id", "19"));
        nvps.add(new BasicNameValuePair("classroom.campus.id", "3"));
        nvps.add(new BasicNameValuePair("classroom.building.id", ""));
        nvps.add(new BasicNameValuePair("seats", ""));
        nvps.add(new BasicNameValuePair("classroom.name", ""));
        nvps.add(new BasicNameValuePair("cycleTime.cycleCount", "1"));
        nvps.add(new BasicNameValuePair("cycleTime.cycleType", "1"));
        nvps.add(new BasicNameValuePair("cycleTime.dateBegin", dateFormat.format(new Date())));
        nvps.add(new BasicNameValuePair("cycleTime.dateEnd", dateFormat.format(new Date())));
        nvps.add(new BasicNameValuePair("roomApplyTimeType", "1"));
        nvps.add(new BasicNameValuePair("timeBegin", timeBegin));
        nvps.add(new BasicNameValuePair("timeEnd", timeEnd));
        nvps.add(new BasicNameValuePair("pageNo", "1"));
        nvps.add(new BasicNameValuePair("pageSize", "1000"));
        return nvps;
    }

    private List<List<String>> parseTableHtml(String html) {
        List<List<String>> info = new ArrayList<>();
        if (html == null || "".equals(html)) {
            return info;
        }
        try {
            Document doc = Jsoup.parse(html);
            Element thead = doc.getElementsByTag("thead").first();
            Element tbody = doc.getElementsByTag("tbody").first();
            List<String> heads = new ArrayList<>();
            for (Element th : thead.getElementsByTag("th")) {
                heads.add(th.text());
            }
            info.add(heads);

            for (Element tr : tbody.getElementsByTag("tr")) {
                List<String> raw = new ArrayList<>();
                for (Element td : tr.getElementsByTag("td")) {
                    raw.add(td.text());
                }
                info.add(raw);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return info;
    }

    public List<List<String>> solve(String timeBegin, String timeEnd) {
        String jid = login();
        if (jid == null) {
            System.out.println("ERROR! 未能获得JSESSIONID");
            return null;
        }
//        System.out.println("JSESSIONID:" + jid);
        List<NameValuePair> nvps = getNameValuePair(timeBegin, timeEnd);
        String html = getHtml(jid, nvps);
        return html ==  null ? null : parseTableHtml(html);
    }
}
